package com.sz.app.edi.aspect;

import com.sz.app.edi.base.entity.SynCompanyAccount;
import com.sz.app.edi.base.service.SynCompanyAccountService;
import com.sz.app.edi.constants.EdiErrorCodes;
import com.sz.app.edi.rest.edi.base.EventHead;
import com.sz.app.edi.rest.edi.base.LogisticsRequest;
import com.sz.app.edi.rest.edi.base.Response;
import com.sz.biz.common.customer.service.CustomerUserService;
import com.sz.common.base.exception.BizException;
import com.sz.common.base.exception.ErrorCode;
import com.sz.common.base.i18n.I18nMessages;
import com.sz.common.base.logger.Logger;
import com.sz.common.base.utils.JsonUtils;
import com.sz.common.base.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;


/**
 * Function: EdiHttpControllerFilter. <br>
 * Date: 2017年12月26日 10:46 <br>
 *
 * @author wentao.chang
 */
@WebFilter(filterName = "ediHttpControllerFilter", urlPatterns = "/edi/api/v1/*")
public class EdiHttpControllerFilter implements Filter {

    private Logger logger = Logger.getLogger(this.getClass());


    @Autowired
    protected I18nMessages messageSource;

    @Autowired
    private SynCompanyAccountService synCompanyAccountService;

    @Autowired
    private CustomerUserService customerUserService;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void destroy() {
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) req;
        ServletRequest requestWrapper = new BodyReaderHttpServletRequestWrapper((HttpServletRequest) req);
        //用户请求的方法
        String method = ((HttpServletRequest) req).getRequestURI();
        //客户访问ip
        String ip = httpRequest.getRemoteAddr();
        logger.info("##----------------edi访问 IP:" + ip + "   地址:" + method);

        //是否生成token请求
        boolean isGenerateToken = CommonAuth.isGenerateToken("232");

        if (isGenerateToken) {
            //验证帐号
            String apiKey = httpRequest.getParameter("apiKey");
            if (StringUtils.isEmpty(apiKey)) {
                logger.error("apiKey为空！！");
                writeExceptionResponse(resp, EdiErrorCodes.ERROR_ARGUMENT_EMPTY, new Object[]{"apiKey"});
                return;
            }
            String securityKey = httpRequest.getParameter("securityKey");
            if (StringUtils.isEmpty(apiKey)) {
                logger.error("securityKey为空！！");
                writeExceptionResponse(resp, EdiErrorCodes.ERROR_ARGUMENT_EMPTY, new Object[]{"securityKey"});
                return;
            }
            logger.info("##----------------edi获取token，apikey:" + apiKey + "      securityKey:" + securityKey);

        } else {
            String accessToken = "";
            try {
                StringBuffer jb = new StringBuffer();
                String line = null;

                BufferedReader reader = requestWrapper.getReader();
                while ((line = reader.readLine()) != null)
                    jb.append(line);


                LogisticsRequest logisticsRequest = JsonUtils.toObject(jb.toString(), LogisticsRequest.class);
                EventHead eventHead = logisticsRequest.getEventHead();
                //请求参数
                accessToken = eventHead.getToken();
                if (StringUtils.isEmpty(accessToken)) {
                    logger.error("token为空！！");
                    writeExceptionResponse(resp, EdiErrorCodes.ERROR_ARGUMENT_EMPTY, new Object[]{"access_token"});
                    return;
                }

            } catch (Exception e) {
                logger.error("", e);
                writeExceptionResponse(resp, EdiErrorCodes.ERROR_EDI_JSON_VALID, new Object[]{});
               return;
            }

            logger.info("##----------------edi访问 token:" + accessToken);
            try {
                //检查token有效性 检查edi账户是否被删除
                SynCompanyAccount synCompanyAccount = synCompanyAccountService.validToken(accessToken);
                //检查edi账户对应的用户是否被删除
                if (!customerUserService.isUserValid(synCompanyAccount.getBizAccountId())) {
                    writeExceptionResponse(resp, EdiErrorCodes.ERROR_EDI_USER_VALID, new Object[]{});
                    return;
                }
                req.setAttribute("bizId", synCompanyAccount.getBizId());
                //验证ip
                CommonAuth.validIP(synCompanyAccount, ip);
            } catch (BizException bizException) {
                writeBizExceptionResponse(resp, bizException);
                return;
            }
        }
        chain.doFilter(requestWrapper, resp);
    }

    private void writeExceptionResponse(ServletResponse resp, ErrorCode errorCode, Object[] params) throws IOException {
        Response response = new Response();
        response.setSuccess(false);
        response.setCode(errorCode.getCode() + "");
        response.setMsg(messageSource.getMessage(errorCode.getMessageKey(), params));
        String repStr = JsonUtils.toJSONString(response);
        logger.error(repStr);

        ((HttpServletResponse) resp).setHeader("Content-type", "application/json;charset=utf-8");
        resp.getWriter().write(repStr);
        resp.getWriter().flush();
        resp.flushBuffer();
    }

    private void writeBizExceptionResponse(ServletResponse resp, BizException be) throws IOException {
        logger.error("BizException:", be);
        Response response = new Response();
        response.setSuccess(false);
        response.setCode(be.getErrorCode() + "");
        response.setMsg(be.getMsg());
        String repStr = JsonUtils.toJSONString(response);
        logger.error(repStr);

        ((HttpServletResponse) resp).setHeader("Content-type", "application/json;charset=utf-8");
        resp.getWriter().write(repStr);
        resp.getWriter().flush();
        resp.flushBuffer();
    }


}
